﻿#ifndef LOG_H
#define LOG_H

#include <iostream>
#include <fstream>
#include <string>
#include <mutex>
#include <ctime>
#include <sstream>
#include "../utils/Singleton.h"

enum LogLevel { DEBUG, INFO, WARNING, ERR, FATAL };
enum LogOutputMode { CONSOLE, FILEOUT };

class Logger : public Singleton<Logger>
{
    friend class Singleton<Logger>;

public:
    ~Logger() override
    {
        if (_logFile.is_open()) {
            _logFile.close();
        }
    }

    bool init(LogLevel level = INFO, LogOutputMode mode = CONSOLE,
              const std::string& fileName = "");
    void setLogLevel(LogLevel level) { _logLevel = level; }

    // 流式输出支持
    class LogStream
    {
    public:
        LogStream(Logger& logger, LogLevel level, const std::string& levelStr)
            : _logger(logger), _level(level), _levelStr(levelStr)
        {
        }

        ~LogStream() { _logger.log(_level, _levelStr, _stream.str()); }

        LogStream& operator<<(const QString& value)
        {
            _stream << value.toStdString();
            return *this;
        }

        template <typename T>
        LogStream& operator<<(const T& value)
        {
            _stream << value;
            return *this;
        }

    private:
        Logger& _logger;
        LogLevel _level;
        std::string _levelStr;
        std::ostringstream _stream;
    };

    LogStream debug() { return LogStream(*this, DEBUG, "DEBUG"); }
    LogStream info() { return LogStream(*this, INFO, "INFO"); }
    LogStream warning() { return LogStream(*this, WARNING, "WARNING"); }
    LogStream error() { return LogStream(*this, ERR, "ERROR"); }
    LogStream fatal() { return LogStream(*this, FATAL, "FATAL"); }

private:
    Logger(QObject* parent = nullptr){};
    LogLevel _logLevel{INFO};
    LogOutputMode _outputMode{CONSOLE};
    std::ofstream _logFile;
    std::mutex _logMutex;
    bool _initialized{false};
    void log(LogLevel level, const std::string& levelStr, const std::string& msg);
};

#define CDEBUG() Logger::getInstance().debug()
#define CINFO() Logger::getInstance().info()
#define CWARN() Logger::getInstance().warning()
#define CERROR() Logger::getInstance().error()
#define CFATAL() Logger::getInstance().fatal()

#endif
